package cs271.examples.oop;

//from http://en.wikipedia.org/wiki/Double_dispatch accessed on 9/21/2007
public class SpaceShipsAndAsteroids {

	private static class SpaceShip { }
	private static class GiantSpaceShip extends SpaceShip { }

	private static class Asteroid {

		public void CollideWith(SpaceShip ship) {
			System.out.println("Asteroid hit a SpaceShip");
		}

		public void CollideWith(GiantSpaceShip ship) {
			System.out.println("Asteroid hit a GiantSpaceShip");
		}
	}

	private static class ExplodingAsteroid extends Asteroid {
		public void CollideWith(SpaceShip ship) {
			System.out.println("ExplodingAsteroid hit a SpaceShip");
		}
		public void CollideWith(GiantSpaceShip ship) {
			System.out.println("ExplodingAsteroid hit a GiantSpaceShip");
		}
	}
	
	public static void main(String[] args) {
		SpaceShip spaceShip = new SpaceShip();
		GiantSpaceShip giantSpaceShip = new GiantSpaceShip();
		
		Asteroid asteroid = new Asteroid();
		ExplodingAsteroid explodingAsteroid = new ExplodingAsteroid();
		
		asteroid.CollideWith(spaceShip);
		asteroid.CollideWith(giantSpaceShip);
		
		explodingAsteroid.CollideWith(spaceShip);
		explodingAsteroid.CollideWith(giantSpaceShip);
		
		Asteroid explode = explodingAsteroid;
		explode.CollideWith(spaceShip);
		explode.CollideWith(giantSpaceShip);
		
		//breaks down because no double dispatch
		asteroid.CollideWith((SpaceShip) giantSpaceShip);
		explode.CollideWith((SpaceShip) giantSpaceShip);
		//this is because the function overloading only looks at the static types...
		//not the runtime types, so when we do the cast, we're tricking the type system
		//into giving us an unexpected result.
		
	}
}
